package org.wzy.springaop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;


@Component
@Aspect
public class AnnotationAspect {

	private static final Logger logger = LoggerFactory.getLogger(AnnotationAspect.class);

	// 配置切入点
	// @Pointcut("execution(* org.wzy.springaop.service..*(..))")
	// @Pointcut("execution(* com.test.spring.aop.pointcutexp..JoinPointObjP2.*(..))")
	// @Pointcut("within(com.test.spring.aop.pointcutexp..*)")
	// @Pointcut("this(com.test.spring.aop.pointcutexp.Intf)")
	// @Pointcut("target(com.test.spring.aop.pointcutexp.Intf)")
	// @Pointcut("@within(org.springframework.transaction.annotation.Transactional)")
	// @Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")
	@Pointcut("@annotation(org.wzy.springaop.annotation.AnnotationAspect)")
	public void aspect() {}

	@Before("aspect()")
	public void before(JoinPoint joinPoint) {
		logger.info("before -------> " + joinPoint);
	}

//	@After("aspect()")
//	public void after(JoinPoint joinPoint) {
//		logger.info("after -------> " + joinPoint);
//	}

	@Around("aspect()")
	public void around(JoinPoint joinPoint) {
		long start = System.currentTimeMillis();

		try {
			logger.info("around - toString={}, ", joinPoint.toString());

			((ProceedingJoinPoint) joinPoint).proceed();

			long end = System.currentTimeMillis();

			logger.info("around " + joinPoint + "\t Use time : " + (end - start) + " ms!");
		} catch (Throwable e) {
			long end = System.currentTimeMillis();
			logger.info(
				"around " + joinPoint + "\t Use time : " + (end - start) + " ms with exception: " + e.getMessage());
		}
	}

	@AfterReturning("aspect()")
	public void afterReturn(JoinPoint joinPoint) {
		logger.info("afterReturn " + joinPoint);
	}

	@AfterThrowing(pointcut = "aspect()", throwing = "ex")
	public void afterThrow(JoinPoint joinPoint, Exception ex) {
		logger.info("afterThrow " + joinPoint + "\t" + ex.getMessage());
	}

}
